using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UtilZ.Dotnet.Ex.Base;

namespace UtilZ.Dotnet.Ex.Model
{
    /// <summary>
    /// 值域类型
    /// </summary>
    public enum ValueRangeType
    {
        /// <summary>
        /// 在值域范围内
        /// </summary>
        In,

        /// <summary>
        /// 在值域范围外
        /// </summary>
        Out
    }

    /// <summary>
    /// 值域接口
    /// </summary>
    public interface IValueRange
    {
        /// <summary>
        /// 参数值名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 附加数据
        /// </summary>
        object Tag { get; set; }

        /// <summary>
        /// 验证值是符合值域,不符合抛出ValueRangeException异常
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        void Validate(object value, object obj, MemberInfo memberInfo);

        /// <summary>
        /// 验证值是符合值域,符合返回true,不符合返回false
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>符合返回true,不符合返回false</returns>
        bool TryValidate(object value, object obj, MemberInfo memberInfo);

        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        string GetValueRangeDes(object value, object obj, MemberInfo memberInfo);

    }

    /// <summary>
    /// 值域基类
    /// </summary>
    public abstract class ValueRangeAbs : IValueRange
    {
        private readonly string _name;
        /// <summary>
        /// 参数值名称
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// 附加数据
        /// </summary>
        public object Tag { get; set; }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">参数名</param>
        public ValueRangeAbs(string name)
        {
            this._name = name;
        }

        /// <summary>
        /// 验证值是符合值域,不符合抛出ValueRangeException异常
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        public void Validate(object value, object obj, MemberInfo memberInfo)
        {
            if (!this.PrimitiveValidate(value, obj, memberInfo))
            {
                string valueRangeDes = this.PrimitiveGetValueRangeDes(value, obj, memberInfo);
                throw new ValueRangeException($"字段\"{this._name}\"取值范围为:\"{valueRangeDes}\",值\"{value}\"无效.");
                //if (memberInfo != null)
                //{
                //    throw new ValueRangeException($"字段\"{memberInfo.DeclaringType.FullName}.{memberInfo.Name}\"取值范围为:\"{valueRangeDes}\",值\"{value}\"无效.");
                //}
                //else
                //{
                //    throw new ValueRangeException($"字段\"{this._name}\"取值范围为:\"{valueRangeDes}\",值\"{value}\"无效.");
                //}
            }
        }

        /// <summary>
        /// 验证值是符合值域,不符合抛出ValueRangeException异常
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>验证结果</returns>
        public bool TryValidate(object value, object obj, MemberInfo memberInfo)
        {
            return this.PrimitiveValidate(value, obj, memberInfo);
        }

        /// <summary>
        /// 验证值是符合值域[符合值域返回true,不符合值域返回false]
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>符合值域返回true,不符合值域返回false</returns>
        protected abstract bool PrimitiveValidate(object value, object obj, MemberInfo memberInfo);




        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        public string GetValueRangeDes(object value, object obj, MemberInfo memberInfo)
        {
            return this.PrimitiveGetValueRangeDes(value, obj, memberInfo);
        }

        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        protected abstract string PrimitiveGetValueRangeDes(object value, object obj, MemberInfo memberInfo);
    }


    /// <summary>
    /// 枚举值域
    /// </summary>
    /// <typeparam name="T">枚举值类型</typeparam>
    public class EnumValueRange<T> : ValueRangeAbs
    {
        private readonly Type _enumType;
        private readonly Type _type;

        private readonly IEnumerable<T> _values;
        /// <summary>
        /// 枚举值集合
        /// </summary>
        public IEnumerable<T> Values
        {
            get { return _values; }
        }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">参数名</param>
        /// <param name="values">枚举值集合</param>
        /// <exception cref="ArgumentNullException">枚举值集合为null或空抛出异常</exception>
        public EnumValueRange(string name, IEnumerable<T> values)
            : base(name)
        {
            if (values == null || values.Count() == 0)
            {
                throw new ArgumentNullException(nameof(values));
            }

            this._enumType = typeof(T);
            this._values = values;
            this._type = typeof(T);
        }


        /// <summary>
        /// 验证值是符合值域[符合值域返回true,不符合值域返回false]
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>符合值域返回true,不符合值域返回false</returns>
        protected override bool PrimitiveValidate(object value, object obj, MemberInfo memberInfo)
        {
            if (value == null)
            {
                return this._values.Contains((T)value);
            }

            if (value.GetType() == this._type)
            {
                return this._values.Contains((T)value);
            }
            else
            {
                return this._values.Contains((T)ConvertEx.ConvertToObject(this._type, value));
            }
        }

        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        protected override string PrimitiveGetValueRangeDes(object value, object obj, MemberInfo memberInfo)
        {
            if (this._enumType.IsEnum)
            {
                StringBuilder sb = new StringBuilder();
                Array array = Enum.GetValues(this._enumType);
                foreach (var item in array)
                {
                    if (this._values.Contains((T)item))
                    {
                        if (sb.Length > 0)
                        {
                            sb.Append(',');
                        }
                        sb.Append(item.ToString());
                    }
                }
                return sb.ToString();
            }
            else
            {
                return string.Join(",", this._values);
            }
        }

    }

    /// <summary>
    /// 数值值域
    /// </summary>
    /// <typeparam name="T">数值类型</typeparam>
    public class NumberValueRange<T> : ValueRangeAbs
        where T : struct, IComparable, IConvertible
    {
        private readonly TypeCode _typeCode;
        private readonly List<NumberValueRangeItem<T>> _in = new List<NumberValueRangeItem<T>>();
        private readonly List<NumberValueRangeItem<T>> _notIn = new List<NumberValueRangeItem<T>>();
        private readonly List<NumberValueRangeItem<T>> _values = new List<NumberValueRangeItem<T>>();

        /// <summary>
        /// 所有值集合
        /// </summary>
#if NET4_0
        public List<NumberValueRangeItem<T>> Values
        {
            get { return this._values; }
        }
#else
        public IReadOnlyList<NumberValueRangeItem<T>> Values
        {
            get { return this._values; }
        }
#endif

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">参数名</param>
        /// <param name="min">包含最小值</param>
        /// <param name="max">包含最大值</param>
        /// <param name="compareType">比较类型</param>
        public NumberValueRange(string name, T min, T max, ValueRangeType compareType = ValueRangeType.In)
            : base(name)
        {
            var item = new NumberValueRangeItem<T>(min, max, compareType);
            if (compareType == ValueRangeType.In)
            {
                this._in.Add(item);
            }
            else
            {
                this._notIn.Add(item);
            }

            this._values.Add(item);
            this._typeCode = Type.GetTypeCode(typeof(T));
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">参数名</param>
        /// <param name="items">多个数据段验证</param>
        /// <exception cref="ArgumentNullException"></exception>
        public NumberValueRange(string name, IEnumerable<NumberValueRangeItem<T>> items)
            : base(name)
        {
            if (items == null || items.Count() == 0)
            {
                throw new ArgumentNullException(nameof(items), "集合不为null或空");
            }

            this._typeCode = Type.GetTypeCode(typeof(T));

            foreach (var item in items)
            {
                this._values.Add(item);
                if (item.RangeType == ValueRangeType.In)
                {
                    this._in.Add(item);
                }
                else
                {
                    this._notIn.Add(item);
                }
            }
        }


        /// <summary>
        /// 验证值是符合值域[符合值域返回true,不符合值域返回false]
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>符合值域返回true,不符合值域返回false</returns>
        protected override bool PrimitiveValidate(object value, object obj, MemberInfo memberInfo)
        {
            if (value == null)
            {
                return false;
            }

            switch (this._typeCode)
            {
                case TypeCode.Char:
                    char chValue = Convert.ToChar(value);
                    foreach (var item in this._notIn)
                    {
                        if (chValue >= Convert.ToChar(item.BeginValue) && chValue <= Convert.ToChar(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (chValue >= Convert.ToChar(item.BeginValue) && chValue <= Convert.ToChar(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.SByte:
                    sbyte sbyteValue = Convert.ToSByte(value);
                    foreach (var item in this._notIn)
                    {
                        if (sbyteValue >= Convert.ToSByte(item.BeginValue) && sbyteValue <= Convert.ToSByte(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (sbyteValue >= Convert.ToSByte(item.BeginValue) && sbyteValue <= Convert.ToSByte(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Byte:
                    byte byteValue = Convert.ToByte(value);
                    foreach (var item in this._notIn)
                    {
                        if (byteValue >= Convert.ToByte(item.BeginValue) && byteValue <= Convert.ToByte(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (byteValue >= Convert.ToByte(item.BeginValue) && byteValue <= Convert.ToByte(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.UInt16:
                    ushort uint16Value = Convert.ToUInt16(value);
                    foreach (var item in this._notIn)
                    {
                        if (uint16Value >= Convert.ToUInt16(item.BeginValue) && uint16Value <= Convert.ToUInt16(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (uint16Value >= Convert.ToUInt16(item.BeginValue) && uint16Value <= Convert.ToUInt16(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Int16:
                    short int16Value = Convert.ToInt16(value);
                    foreach (var item in this._notIn)
                    {
                        if (int16Value >= Convert.ToInt16(item.BeginValue) && int16Value <= Convert.ToInt16(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (int16Value >= Convert.ToInt16(item.BeginValue) && int16Value <= Convert.ToInt16(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.UInt32:
                    uint uint32Value = Convert.ToUInt32(value);
                    foreach (var item in this._notIn)
                    {
                        if (uint32Value >= Convert.ToUInt32(item.BeginValue) && uint32Value <= Convert.ToUInt32(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (uint32Value >= Convert.ToUInt32(item.BeginValue) && uint32Value <= Convert.ToUInt32(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Int32:
                    int int32Value = Convert.ToInt32(value);
                    foreach (var item in this._notIn)
                    {
                        if (int32Value >= Convert.ToInt32(item.BeginValue) && int32Value <= Convert.ToInt32(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (int32Value >= Convert.ToInt32(item.BeginValue) && int32Value <= Convert.ToInt32(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.UInt64:
                    ulong uint64Value = Convert.ToUInt64(value);
                    foreach (var item in this._notIn)
                    {
                        if (uint64Value >= Convert.ToUInt64(item.BeginValue) && uint64Value <= Convert.ToUInt64(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (uint64Value >= Convert.ToUInt64(item.BeginValue) && uint64Value <= Convert.ToUInt64(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Int64:
                    long int64Value = Convert.ToInt64(value);
                    foreach (var item in this._notIn)
                    {
                        if (int64Value >= Convert.ToInt64(item.BeginValue) && int64Value <= Convert.ToInt64(item.EndValue))
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        if (int64Value >= Convert.ToInt64(item.BeginValue) && int64Value <= Convert.ToInt64(item.EndValue))
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Single:
                    float floatValue = Convert.ToSingle(value);
                    double floatPre;

                    foreach (var item in this._notIn)
                    {
                        floatPre = Convert.ToSingle(item.Precision);
                        if (floatValue - Convert.ToSingle(item.BeginValue) > floatPre && floatValue - Convert.ToSingle(item.EndValue) < floatPre)
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        floatPre = Convert.ToSingle(item.Precision);
                        if (floatValue - Convert.ToSingle(item.BeginValue) > floatPre && floatValue - Convert.ToSingle(item.EndValue) < floatPre)
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Double:
                    double doubleValue = Convert.ToDouble(value);
                    double doublePre;
                    foreach (var item in this._notIn)
                    {
                        doublePre = Convert.ToDouble(item.Precision);
                        if (doubleValue - Convert.ToDouble(item.BeginValue) > doublePre && doubleValue - Convert.ToDouble(item.EndValue) < doublePre)
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        doublePre = Convert.ToDouble(item.Precision);

                        if (doubleValue - Convert.ToDouble(item.BeginValue) > doublePre && doubleValue - Convert.ToDouble(item.EndValue) < doublePre)
                        {
                            return true;
                        }
                    }
                    break;
                case TypeCode.Decimal:
                    decimal decimalValue = Convert.ToDecimal(value);
                    decimal decimalPre;
                    foreach (var item in this._notIn)
                    {
                        decimalPre = Convert.ToDecimal(item.Precision);
                        if (decimalValue - Convert.ToDecimal(item.BeginValue) > decimalPre && decimalValue - Convert.ToDecimal(item.EndValue) < decimalPre)
                        {
                            return false;
                        }
                    }

                    foreach (var item in this._in)
                    {
                        decimalPre = Convert.ToDecimal(item.Precision);
                        if (decimalValue - Convert.ToDecimal(item.BeginValue) > decimalPre && decimalValue - Convert.ToDecimal(item.EndValue) < decimalPre)
                        {
                            return true;
                        }
                    }
                    break;
                default:
                    throw new NotSupportedException($"不支持的类型{typeof(T).FullName}");
            }

            return false;
        }


        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        protected override string PrimitiveGetValueRangeDes(object value, object obj, MemberInfo memberInfo)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in this._in)
            {
                if (sb.Length > 0)
                {
                    sb.Append(',');
                }
                sb.Append(item.RangeType.ToString());
                sb.Append(' ');
                sb.Append(item.BeginValue);
                sb.Append('-');
                sb.Append(item.EndValue);
            }

            foreach (var item in this._notIn)
            {
                if (sb.Length > 0)
                {
                    sb.Append(',');
                }
                sb.Append(item.RangeType.ToString());
                sb.Append(' ');
                sb.Append(item.BeginValue);
                sb.Append('-');
                sb.Append(item.EndValue);
            }
            return sb.ToString();
        }

    }

    /// <summary>
    /// 数值值域项
    /// </summary>
    /// <typeparam name="T">数值类型</typeparam>
    public class NumberValueRangeItem<T> where T : struct, IComparable, IConvertible
    {
        /// <summary>
        /// 起始值(包含)
        /// </summary>
        public T BeginValue { get; private set; }

        /// <summary>
        /// 结束值(包含)
        /// </summary>
        public T EndValue { get; private set; }

        /// <summary>
        /// 值域类型
        /// </summary>
        public ValueRangeType RangeType { get; private set; }

        /// <summary>
        /// 浮点数精度
        /// </summary>
        public T Precision { get; set; } = default(T);



        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="beginValue">包含最小值</param>
        /// <param name="endValue">包含最大值</param>
        /// <param name="rangeType">值域类型</param>
        public NumberValueRangeItem(T beginValue, T endValue, ValueRangeType rangeType)
        {
            if (beginValue.CompareTo(endValue) > 0)
            {
                throw new ArgumentException($"起始值{beginValue}不能大于结束值{endValue}");
            }

            this.BeginValue = beginValue;
            this.EndValue = endValue;
            this.RangeType = rangeType;
        }

        /// <summary>
        /// 构造函数,值域类型默认为ValueRangeType.In
        /// </summary>
        /// <param name="beginValue">包含最小值</param>
        /// <param name="endValue">包含最大值</param>
        public NumberValueRangeItem(T beginValue, T endValue)
        {
            if (beginValue.CompareTo(endValue) > 0)
            {
                throw new ArgumentException($"起始值{beginValue}不能大于结束值{endValue}");
            }

            this.BeginValue = beginValue;
            this.EndValue = endValue;
            this.RangeType = ValueRangeType.In;
        }


        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return $"{this.RangeType.ToString()} {this.BeginValue}-{this.EndValue}";
        }



        /// <summary>
        /// 解析范围字符串
        /// </summary>
        /// <param name="rangeStr">范围字符串,示例:36.5-78-i|65-85-o|...</param>
        /// <returns>解析结果</returns>
        /// <exception cref="ArgumentException"></exception>
        public static List<NumberValueRangeItem<T>> Parse(string rangeStr)
        {
            List<NumberValueRangeItem<T>> result;
            string err;
            if (PrimitiveTryParse(ref rangeStr, ValueRangeType.In, out result, out err))
            {
                return result;
            }
            else
            {
                throw new ArgumentException(err);
            }
        }

        /// <summary>
        /// 解析范围字符串
        /// </summary>
        /// <param name="rangeStr">范围字符串,示例:36.5-78-i|65-85-o|...</param>
        /// <returns>解析结果</returns>
        /// <param name="defaultRangeType">默认范围类型,用于范围段中未指定范围类型场景</param>
        /// <exception cref="ArgumentException"></exception>
        public static List<NumberValueRangeItem<T>> Parse(string rangeStr, ValueRangeType defaultRangeType)
        {
            List<NumberValueRangeItem<T>> result;
            string err;
            if (PrimitiveTryParse(ref rangeStr, defaultRangeType, out result, out err))
            {
                return result;
            }
            else
            {
                throw new ArgumentException(err);
            }
        }

        /// <summary>
        /// 尝试解析范围字符串,解析成功返回true,解析失败返回false
        /// </summary>
        /// <param name="rangeStr">范围字符串,示例:36.5-78-i|65-85-o|...</param>
        /// <param name="result">解析结果</param>
        /// <returns>解析成功返回true,解析失败返回false</returns>
        public static bool TryParse(string rangeStr, out List<NumberValueRangeItem<T>> result)
        {
            string err;
            return PrimitiveTryParse(ref rangeStr, ValueRangeType.In, out result, out err);
        }

        /// <summary>
        /// 尝试解析范围字符串,解析成功返回true,解析失败返回false
        /// </summary>
        /// <param name="rangeStr">范围字符串,示例:36.5-78-i|65-85-o|...</param>
        /// <param name="result">解析结果</param>
        /// <param name="defaultRangeType">默认范围类型,用于范围段中未指定范围类型场景</param>
        /// <returns>解析成功返回true,解析失败返回false</returns>
        public static bool TryParse(string rangeStr, out List<NumberValueRangeItem<T>> result, ValueRangeType defaultRangeType)
        {
            string err;
            return PrimitiveTryParse(ref rangeStr, defaultRangeType, out result, out err);
        }

        private static bool PrimitiveTryParse(ref string rangeStr, ValueRangeType defaultRangeType, out List<NumberValueRangeItem<T>> result, out string err)
        {
            //36.5-78-i|65-85-o|...

            result = null;
            if (string.IsNullOrEmpty(rangeStr))
            {
                err = "范围字符串为空或null";
                return false;
            }

            err = null;
            string[] strs = rangeStr.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            result = new List<NumberValueRangeItem<T>>(strs.Length);
            object itemValue1, itemValue2;
            char[] separator = new char[] { '-' };

            ValueRangeType rangeType;
            for (int i = 0; i < strs.Length; i++)
            {
                string[] itemStrs = strs[i].Split(separator, StringSplitOptions.RemoveEmptyEntries);
                if (itemStrs.Length < 2)
                {
                    err = $"\"{strs[i]}\"无效";
                    return false;
                }

                if (!ConvertEx.TryConvertTo(typeof(T), itemStrs[0], out itemValue1))
                {
                    err = $"\"{strs[i]}\"无效";
                    return false;
                }

                if (!ConvertEx.TryConvertTo(typeof(T), itemStrs[1], out itemValue2))
                {
                    err = $"\"{strs[i]}\"无效";
                    return false;
                }

                if (itemStrs.Length == 2)
                {
                    rangeType = defaultRangeType;
                }
                else if (itemStrs.Length == 3)
                {
                    if (string.Equals(itemStrs[2], "i", StringComparison.OrdinalIgnoreCase))
                    {
                        rangeType = ValueRangeType.In;
                    }
                    else if (string.Equals(itemStrs[2], "o", StringComparison.OrdinalIgnoreCase))
                    {
                        rangeType = ValueRangeType.Out;
                    }
                    else
                    {
                        rangeType = (ValueRangeType)Enum.Parse(typeof(ValueRangeType), itemStrs[2]);
                    }
                }
                else
                {
                    err = $"\"{strs[i]}\"无效";
                    return false;
                }

                result.Add(new NumberValueRangeItem<T>((T)itemValue1, (T)itemValue2, rangeType));
            }

            return true;
        }



    }

    /// <summary>
    /// 多个值域
    /// </summary>
    public class MultiValueRange : IValueRange
    {
        private readonly string _name;
        /// <summary>
        /// 参数值名称
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// 附加数据
        /// </summary>
        public object Tag { get; set; }


        private readonly IValueRange[] _valueRanges;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">参数名</param>
        /// <param name="valueRanges">多个值域集合</param>
        public MultiValueRange(string name, IEnumerable<IValueRange> valueRanges)
        {
            this._name = name;
            this._valueRanges = valueRanges.ToArray();
        }


        /// <summary>
        /// 验证值是符合值域,不符合抛出ValueRangeException异常
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        public void Validate(object value, object obj, MemberInfo memberInfo)
        {
            foreach (var valueRange in this._valueRanges)
            {
                if (valueRange.TryValidate(value, obj, memberInfo))
                {
                    return;
                }
            }

            string valueRangeDes = this.GetValueRangeDes(value, obj, memberInfo);
            if (memberInfo != null)
            {
                throw new ValueRangeException($"值\"{value}\"不满足\"{memberInfo.DeclaringType.FullName}.{memberInfo.Name}\"值域:\"{valueRangeDes}\"");
            }
            else
            {
                throw new ValueRangeException($"值\"{value}\"不满足值域:\"{valueRangeDes}\"");
            }
        }

        /// <summary>
        /// 验证值是符合值域,不符合抛出ValueRangeException异常
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>验证结果</returns>
        public bool TryValidate(object value, object obj, MemberInfo memberInfo)
        {
            foreach (var valueRange in this._valueRanges)
            {
                if (valueRange.TryValidate(value, obj, memberInfo))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 获取值域描述
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="obj">值所属对象</param>
        /// <param name="memberInfo">属性或字段信息</param>
        /// <returns>值域描述</returns>
        public string GetValueRangeDes(object value, object obj, MemberInfo memberInfo)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var valueRange in this._valueRanges)
            {
                sb.AppendLine(valueRange.GetValueRangeDes(value, obj, memberInfo));
            }
            return sb.ToString();
        }
    }

}
